package locusts;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
import locusts.common.entities.Vehicle;
import locusts.lib.FrameCounter;
import locusts.lib.Shapes;

class DrawArea extends JPanel {

    private static final RenderingHints HINTS = getRenderingHints();
    static final Shape BOID_POLY = Shapes.createTriangle(0, 0, 3, 4);
    FrameCounter frameCounter;
    Game game;
    AffineTransform viewTransform;
    AffineTransform viewTransformTarget;

    public DrawArea(Game game) {
        super();
        frameCounter = new FrameCounter("Graphics");
        this.game = game;
        viewTransform = new AffineTransform();
        viewTransformTarget = new AffineTransform();
        setFocusable(true);
        addKeyListener(new ViewTranslateKeyListener(viewTransformTarget));
        requestFocus();
        new Timer("Graphics Update Timer").schedule(new TimerTask() {

            @Override
            public void run() {
                repaint();
            }
        }, 0, 1000 / 60);
    }

    @Override
    public void paint(Graphics g) {
        frameCounter.markFrame();
        super.paint(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHints(HINTS);
        AffineTransform saveAT = g2.getTransform();

        double[] m0 = new double[6], m1 = new double[6];
        viewTransform.getMatrix(m0);
        viewTransformTarget.getMatrix(m1);

        for(int i = 0; i < m0.length; i++) {
            m0[i] *= 0.9d;
            m0[i] += m1[i] * 0.1d;
        }
        viewTransform = new AffineTransform(m0);

        

        g2.transform(viewTransform);
        // scale and translate to fit the scene

        for (Vehicle boid : game.flock.getBoids()) {
            paintBoid(g2, boid);
        }


        g2.setTransform(saveAT);
        g2.drawString(frameCounter.toString(), 10, 20);
        g2.drawString(game.frameCounter.toString(), 10, 40);
//        g2.drawString("Transform: " + viewTransform, 10, 60);

        g2.drawString("Use arrow keys to scroll, +/- to zoom.", 10, getHeight()-10);
    }

    public void paintBoid(Graphics2D g2, Vehicle v) {
        AffineTransform saveAT = g2.getTransform();
        g2.translate(v.position.x, v.position.y);
        g2.rotate(v.heading() + Math.PI / 2.0);
        g2.draw(BOID_POLY);
        g2.setTransform(saveAT);
    }

    public static RenderingHints getRenderingHints() {
        RenderingHints hints = new RenderingHints(
                RenderingHints.KEY_ALPHA_INTERPOLATION,
                RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        hints.put(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        hints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        hints.put(RenderingHints.KEY_COLOR_RENDERING,
                RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_DISABLE);
        hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
                RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        hints.put(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        hints.put(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_STROKE_CONTROL,
                RenderingHints.VALUE_STROKE_PURE);
        return hints;
    }
}
